package com.xc.file.web.rest.open;

import com.xc.api.basic.BasicApi;
import com.xc.config.aspect.AspectConstants;
import com.xc.core.bean.SignBean;
import com.xc.core.dto.SignDto;
import com.xc.core.dto.UploadDto;
import com.xc.core.enums.EffectStatus;
import com.xc.core.enums.SignType;
import com.xc.file.bean.SignUploadBean;
import com.xc.file.config.Constants;
import com.xc.file.enums.FailCode;
import com.xc.file.enums.UploadType;
import com.xc.file.model.UploadModel;
import com.xc.file.service.UploadService;
import com.xc.tool.utils.Base64Utils;
import com.xc.tool.utils.JSONUtils;
import com.xc.tool.utils.ObjectUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.nio.charset.Charset;
import java.util.Hashtable;
import java.util.Map;
import java.util.TreeMap;

/**
 * <p>开放接口，上传管理</p>
 *
 * @author xc
 * @version v1.0.0
 */
@Api(tags = "开放接口，上传管理")
@RestController
public class OpenUploadRest {
    private static Map<String, SignDto> appMap = new Hashtable<>();

    @Autowired
    private UploadService uploadService;
    @Autowired
    private Constants constants;
    @Autowired
    private BasicApi basicApi;
    @Autowired
    private AspectConstants aspectConstants;

    @ApiOperation(value = "上传文件",
            notes = "开放接口,签名方式上传,文件储存在该用户的网盘目录下，1，单次上传，传入的size和文件的size必须相等\n" +
                    "2，分段上传，首次请求fileIndex必须等于零，根据返回的renewalSize确定每次上传多少\n" +
                    "3，md5签名顺序appId，folderNames，randomStr，timeStamp")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "文件数据", name = "file", paramType = "body", required = true),
    })
    @PostMapping("/open/upload_file")
    public UploadDto openUploadFile(SignUploadBean signUploadBean, @RequestPart("file") MultipartFile file) {
        if (file == null) {
            throw FailCode.FILE_NOT_EMPTY.getOperateException();
        }
        // 验证签名,并缓存签名
        String key = signUploadBean.getSign();
        SignDto signDto = appMap.get(key);
        if (signDto == null) {
            // 签名传递的数据
            Map<String, Object> signMap = new TreeMap<>();
            signMap.put("appId", signUploadBean.getAppId());
            signMap.put("fixedPath", signUploadBean.getFixedPath());
            signMap.put("randomStr", signUploadBean.getRandomStr());
            signMap.put("timeStamp", signUploadBean.getTimeStamp());
            String json = JSONUtils.getStringByObject(signMap);
            // 验证签名数据
            SignBean signBean = new SignBean(signUploadBean.getAppId(), SignType.MD5_SIGN);
            signBean.setSign(signUploadBean.getSign());
            signBean.setSignData(Base64Utils.encodeToString(json.getBytes(Charset.forName("utf-8"))));
            signBean.setAuthorityCode("openSignUploadFile");
            signBean.setMyAppId(aspectConstants.getAppId());
            signDto = basicApi.verifySign(signBean);
            appMap.put(key, signDto);
        }
        // 封装数据上传文件
        UploadModel uploadModel = ObjectUtils.convert(new UploadModel(), signUploadBean);
        uploadModel.setFile(file);
        uploadModel.setStatus(EffectStatus.INVALID.getStatus());
        uploadModel.setUserId(signDto.getUserId());
        uploadModel.setUploadType(UploadType.SIGN);
        UploadDto uploadDto = uploadService.uploadFile(uploadModel);
        // 上传完成
        if (uploadDto.getFinish()) {
            appMap.remove(key);
            uploadDto.setDownloadUrl(constants.getLocalUrl() + constants.getOpenDownloadUrl() + signDto.getUserId() + uploadDto.getFilePath());
        }
        // 返回续传地址
        if (uploadDto.getUploadUrl() != null) {
            uploadDto.setUploadUrl(uploadDto.getUploadUrl() + "/open/upload_file");
        } else {
            uploadDto.setUploadUrl(constants.getLocalUrl() + "/open/upload_file");
        }
        return uploadDto;
    }
}
